home *** CD-ROM | disk | FTP | other *** search
/ The Business Master (3rd Edition) / The Business Master (3rd Edition).iso / files / utilstic / showmcb / showmcbs.asm < prev    next >
Encoding:
Assembly Source File  |  1993-01-28  |  59.3 KB  |  1,161 lines

  1.         Title       ShowMCBs -- Program to scroll MCB Information
  2. Comment !                                    28-Jan-1993 00:05:20
  3.         Author:     Tom Gilbert's Heart&Mind
  4.                     7127 Lafayette Avenue
  5.                     Kansas City, KS 66109
  6.                     (913) 299-2701
  7.  
  8.         Copyright   (c) 1988/93 by Heart & Mind
  9.                     for NON-Commercial Use ONLY
  10.                     Use and distribution in the
  11.                     Public Domain is encouraged!
  12.  
  13. MCB     Struc                   ; Information from MemoryControlBlock
  14. blkA    DW  0                           ; MCB Segment Address
  15. blkB    DW  0                           ; Block Type Letter & Code
  16. blkC    DW  0                           ; Controlled Area Segment
  17. blkL    DW  0                           ; Length of Controlled Area
  18. blkN    DB  8 DUP (0)                   ; Identification of Area
  19. MCB     EndS                    ; End of MCB Information Structure
  20. Cseg    Segment Public Para
  21.         Assume  CS:Cseg,  SS:Cseg ,DS:Nothing, ES:Nothing
  22.         Org     100h
  23. Begin:  Jmp     Main
  24. exKeys  DB 65,71,72,73,79,80,81 ; Extended Key Scan Codes
  25. LexKeys EQU $-exKeys            ; Number of Codes in Table
  26. XMSmgr  DB  3                   ; 386MAX, 2=RM386, 1=QEMM386, 0=DOS
  27. SubF    DB  0                   ; Set to 1 If in Sub-Blocks
  28. Menv    DW  ?                   ; Segment of Master Environment
  29. Next    DW  ?                   ; Segment of Next Major MCB
  30. MCBS    MCB 100 DUP (<>)        ; Paragraph Aligned MCB Array
  31. SavePtr DW  OFFSET MCBS
  32. XMS     DD  0
  33. headline    DB  ' >ShowMCBs  Version 5.2 for DOS 5.0 or equivalent'
  34.             DB  " - by Tom Gilbert's Heart&Mind",13,10
  35.             DB  '      Type Of  Block Owner Program',13,10
  36.             DB  '  MCB Mem Area  SEG Length Identity'
  37.             DB  '   Command Line   Chained/Hooked INT Vectors',13,10
  38.             DB  ' ---- -------- ---- ------ --------'
  39.             DB  ' ---------------- --------------------------',13,10
  40. statline    DB  ' Line:    of   '
  41.             DB  ' Move:   PgUg PgDn Home End or Exit: by Esc'
  42.             DB  ' or F7 to PrintMCBs '
  43. BytesE      DB  ' KiloBytes of Extended Memory available.',13,10
  44.             DB  ' KiloBytes in an available single block.',13,10
  45. BytesM      DB  ' bytes of conventional memory available at'
  46. MsgLen      EQU $ - BytesM
  47. FkeyMsg     DB 'Press F8 for output to filename ShowMCBs.PRN',0
  48. helpdat DB 13,10,255,'       '
  49.             DB 'Press F7 for report output to file or PRN.',13,10
  50. DB 13,10,'  ',76 DUP ("*"),13,10
  51. DB       '  IF you can ONLY get this HELP screen, '
  52. DB       'THEN you need DOS 5.0 or an equivalent',13,10
  53. DB       '  ',76 DUP ("*"),13,10,13,10,"        "
  54. DB "ShowMCBs displays all MCBs in the 1st MEG of computer memory."
  55. DB 13,10,13,10
  56. DB ' "MCB" stands for "Memory Control Block".  It controls',13,10
  57. DB '              the area beginning at the next paragraph.'
  58. DB 13,10
  59. DB ' The "Mem Area" lists the "Type Of" controlled block or sub-block.'
  60. DB 13,10,'           '
  61. DB 'The "SEG" is the Segment at which an "Owner" area begins.'
  62. DB 13,10,'           '
  63. DB 'If "0000" the next memory area is "available" for use.'
  64. DB 13,10,'           '
  65. DB 'If "0008" or less the next memory area belongs to the system.'
  66. DB 13,10,'               '
  67. DB 'The "Length" is decimal bytes for the area after the "MCB".'
  68. DB 13,10,'           '
  69. DB '              A large area not followed by sub-blocks located in'
  70. DB 13,10,20 DUP (' '),'UPPER memory may be Video or an EMS page frame.'
  71. DB 13,10
  72. DB 13,10,'                      The "Identity" may be a "FileName" or'
  73. DB 13,10,'                      "DOS S"ystem"C"ode, or "S"ystem"D"ata.'
  74. DB 13,10,'                          "Filename" may be for an'
  75. DB 13,10,'                         "<Environment>" or "<FarDataArea>".'
  76. DB 13,10,'                       If "Filename" is a process,'
  77. DB 13,10,20 DUP (' '),'            then "Command Line" is parameters.'
  78. DB 13,10,13,10,40 DUP (' '),'               All INTerrupt vectors'
  79. DB 13,10,30 DUP (' '),'                      once WATCH is installed.'
  80. DB 13,10,30 DUP (' '),'                   Otherwise top of the chain.'
  81. DB 13,10,13,10
  82. DB " If expanded memory is installed, the Manager's Version number,"
  83. DB 13,10
  84. DB ' Page Frame Segment (through which memory is windowed) and block'
  85. DB 13,10
  86. DB ' information will be shown.  User names are shown if provided.'
  87. DB 13,10,13,10
  88. DB '            The largest free Extended and Conventional memory'
  89. DB 13,10
  90. DB '            blocks display as "available" KiloBytes and bytes.'
  91. DB 13,10
  92. DB 13,10,'  F7-F7 will print the display and F7-F8 makes ShowMCBs.PRN'
  93. DB 13,10,13,10
  94. DB '                       ***** End of ShowMCBs Help *****',13,10
  95. helplen equ $-helpdat
  96. Sbuffer     DW      ?           ; Start of Buffer
  97. Pbuffer     DW      ?           ; Position in Buffer
  98. Lbuffer     DW      8000h       ; Length of Buffer
  99. Ebuffer     DW      ?           ; End of Buffer
  100. LineNum     DW      ?           ; Data buffer line
  101. LastNum     DW      ?           ; Last buffer line
  102. columns    EQU      80          ; Number of columns used per row
  103. rows        DW      24          ; Number of last row for display
  104. datrows     DW      20          ; Number of data rows per page
  105. lastrow     DW      24          ; Number of last display row
  106. attr        DB      ?           ; Video Attribute
  107. mode        DB      ?           ; Initial mode
  108. pag         DB      ?           ; Initial display page
  109. NewVid      DB      0           ; Video change flag
  110. cga         DB      1           ; CGA flag - default yes
  111. VidAdr      DW    0B800h        ; Color Video buffer address
  112. mono       EQU    0B000h        ; Monochrome address
  113. StatAtr     DB      030h        ; Color default - black on cyan
  114. BWstat     EQU      070h        ; B&W default - black on white
  115. ScrnAtr     DB      017h        ; Color default - white on blue
  116. BWscrn     EQU      007h        ; B&W default - white on black
  117. Watch       DB "WATCH"          ; WATCH Command Line Parameter
  118. WatchF      DW  0               ; MCB Index to WATCH PSP if Set
  119. Vpos        DW  ?               ; WATCH Next PSP-ID Position
  120. DisaM       DB "***  D I S A B L E D  ***"
  121. DisaLen    EQU $-DisaM
  122. EMSerm      DB 13,10,'   *** Expanded Memory NOT Installed'
  123.             DB ' or NOT Working ***',13,10
  124. emerml     EQU $-EMSerm
  125. emmshdg     DB 13,10,' block    pages   KBytes   UserName  '
  126.             DB '  (Expanded Memory - Version '
  127. emmlen1    EQU $-emmshdg
  128. dashes      DB 13,10,' -----    -----   ------   --------  '
  129.             DB '  (LIM page frame address -'
  130. emmlen2    EQU $-emmshdg-emmlen1
  131. handles     DW 0                ; E/Xms handles - default none
  132. EmsName     DB 'EMMXXXX0'       ; EMM standard Name
  133. Tpages      DW 0                ; Page accumulator
  134. TotlM       DB ' Total'
  135. FreeM       DB ' Free '
  136. DOSm        DB '  DOS '
  137. SubCBIs     DB  'BCDEFILMSXZ'   ; Codes 10=B -- Z=0
  138. TypeMCB     DB  'Zmemory X FCBS= Stacks= Memory  LastDrv '
  139.             DB  'In-File Files=  Extra ? Device= C Buff= Buffers '
  140. IsFar       DB  "<FarDataArea>"
  141.             DB  "<Environment>"
  142.             DB  "<386MAX Data>"
  143.             DB  "<Master Env.>"
  144.  
  145. Main        PROC
  146.             Mov     DI,Offset Buffer    ; Save Offset of
  147.             Mov     Sbuffer,DI          ; Display Buffer in
  148.             Mov     Pbuffer,DI          ; Position to Start
  149.             Mov     CX,Lbuffer          ; Initialize Length
  150.             Shr     CX,1                ; Use Word
  151.             Mov     AX,"  "             ; Spaces to
  152.             Rep     StoSW               ; SetUp Buffer
  153.             Mov     Ebuffer,DI
  154.             Mov     AX,352Eh
  155.             Int     21h                 ; Get Segment of the
  156.             Mov     BX,ES:[2Ch]         ; Master Environment
  157.             Mov     Menv,BX
  158.             Mov     ES,CS:[2Ch]         ; Set Pointer to the
  159.             Xor     DI,DI               ; ShowMCBs Environment
  160.             Xor     AX,AX               ; Find Double NULL End
  161.             Mov     CX,8000h            ; Before the File Spec.
  162. Find00:     RepNE   ScaSB               ; Find First Null Byte
  163.             Dec     CX                  ; Count While Checking
  164.             ScaSB                       ; If NOT Second NULL
  165.             Jne     Find00              ; Then Continue Scans
  166.             Mov     AL,"."              ; Else Find Filename End
  167.             RepNE   ScaSB
  168.             Dec     DI                  ; Point to End "." and
  169.             Mov     CX,DI               ; Initialize Counter
  170.             Push    DI                  ; Preserve Pointer and
  171.             Push    CX                  ; Counter Values
  172.             STD                         ; Work Backwards
  173.             Mov     AL,"\"              ; Look for Path
  174.             RepNE   ScaSB
  175.             Mov     SI,DI               ; Save Position and
  176.             Pop     CX                  ; Restore Counter/Pointer
  177.             Pop     DI                  ; If Path Found
  178.             Je      FNless2             ; Then Filename Inside
  179.             Mov     AL,":"              ; Else Search for Drive
  180.             RepNE   ScaSB
  181.             Mov     SI,DI               ; Save Position and
  182. FNless2:    Add     SI,2                ; Adjust to FN 1st Byte
  183.             Mov     DI,SI               ; Set Pointer and
  184.             Sub     CX,DI               ; Calculate Length to
  185.             CLD                         ; Compare Forward
  186.             Mov     SI,CS
  187.             Dec     SI                  ; Point to
  188.             Mov     DS,SI               ; MCB Para.
  189.             Mov     SI,8                ; Filename
  190.             RepE    CmpSB
  191.             Push    CS                  ; If Filename
  192.             Pop     DS                  ; NOT in MCB
  193.             Jne     HelpOpt             ; Then Give HELP
  194.             Mov     AX,4300h            ; Else Check for
  195.             Int     2Fh                 ; XMS Manager
  196.             Cmp     AL,80h              ; If NOT Installed
  197.             Jne     GetData             ; Then Leave Zero
  198.             Mov     AX,4310h            ; Else Get Control
  199.             Int     2Fh
  200.             Mov     Word Ptr XMS,BX     ; Store Vector
  201.             Mov     Word Ptr XMS+2,ES
  202.             Mov     AH,8                ; Get Largest and
  203.             Call    XMS                 ; Total Kb Blocks
  204.             Mov     Word Ptr XMS+2,AX   ; Save EMS Kb Report
  205.             Mov     Word Ptr XMS,DX
  206. GetData:    Mov     AH,52h              ; From List of Lists
  207.             Int     21h                 ; Get Address of the
  208.             Mov     BP,ES:[BX-2]        ; First MCB to
  209.             Mov     CS:Next,BP          ; Be Buffered
  210.             Mov     DS,BP               ; Point to 1st
  211.             Mov     AX,DS:[24]          ; Device Name
  212.             Cmp     AX,"83"             ; If 386MAX
  213.             Je      GotMgr              ; Then Default
  214.             Dec     CS:XMSmgr           ; Else If
  215.             Cmp     AX,"MR"             ; Is RM386
  216.             Je      GotMgr              ; Then Set
  217.             Dec     CS:XMSmgr           ; Else If
  218.             Cmp     AX,"EQ"             ; QEMM386
  219.             Je      GotMgr              ; Then Set
  220.             Dec     CS:XMSmgr           ; Else DOS
  221. GotMgr:     Push    CS                  ; Set Extra
  222.             Pop     ES                  ; Segment for
  223.             Mov     DI,CS:SavePtr       ; MCBS Storage
  224.             Call    GetMCBs
  225. HelpOpt:    Mov     SI,OFFSET helpdat   ; Set Source to Help and
  226.             Mov     DI,Pbuffer          ; Destination to Position
  227.             Mov     CX,helplen
  228.             Rep     MovSB               ; Copy help data and
  229.             Mov     Ebuffer,DI          ; Store End Position
  230.             Sub     DI,Sbuffer
  231.             Mov     Lbuffer,DI          ; Store Length Used
  232.             Mov     DI,Ebuffer
  233.             Call    Lines2Top           ; Count and Store
  234.             Mov     LastNum,AX          ; Lines to Buffer End
  235.             Mov     AH,12h
  236.             Mov     BL,10h              ; Call for EGA/VGA status
  237.             Xor     CX,CX               ; With Clear status bits
  238.             Int     10h
  239.             Xor     AX,AX
  240.             JcxZ    modechk             ; If status is still Clear
  241.             Mov     ES,AX               ; or if EGA is NOT active
  242.             Test    BYTE PTR ES:[487h],1000b
  243.             Jnz     modechk             ; Then check CGA or Mono Mode
  244.             Mov     AX,1130h            ; Else get EGA information
  245.             Int     10h
  246.             Mov     AL,DL               ; Make lines per screen
  247.             CBW                         ; into a Word Value
  248.             Mov     rows,AX             ; Reset number of the
  249.             mov     lastrow,AX          ; last row and number
  250.             Sub     AX,4                ; of rows available for
  251.             Mov     datrows,AX          ; data from their defaults
  252.             Dec     cga                 ; Clear the CGA Flag
  253. modechk:    Push    CS
  254.             Pop     ES
  255.             Mov     AH,0Fh              ; Get video mode
  256.             Int     10h
  257.             Mov     mode,AL             ; Save initial
  258.             Mov     pag,BH              ; mode and page
  259.             Mov     DL,AL               ; Work on copy
  260.             Cmp     DL,7                ; If mono 7
  261.             Je      loadmono            ; Then Set mono
  262.             Cmp     DL,15               ; Else If NOT mono 15
  263.             Jne     graphchk            ; Then Check graphics
  264. loadmono:   Mov     VidAdr,mono         ; Else Load mono address
  265.             Mov     StatAtr,BWstat      ; Set B&W defaults for status
  266.             Mov     ScrnAtr,BWscrn      ; line and screen background
  267.             Dec     cga                 ; Set as NOT CGA
  268.             Cmp     AL,15               ; If NOT mono 15
  269.             Jne     VidExit             ; Then Done
  270.             Mov     DL,7                ; Else Set standard mono
  271.             Jmp     SHORT chmode
  272. graphchk:   Cmp     DL,7                ; If 7 or higher
  273.             Jg      color               ; Then color or done
  274.             Cmp     DL,4                ; Else 5 and 6 are
  275.             Jg      bnw                 ; usually black and white
  276.             Je      color               ; 4 is color
  277.             Test    DL,1                ; AND
  278.             Jz      bnw                 ; 0 and 2 are black and white
  279. color:      Cmp     DL,3                ; If mode 3
  280.             Je      VidExit             ; Then Done
  281.             Mov     DL,3                ; Else use color text mode
  282.             Jmp     SHORT chmode
  283. bnw:        Mov     StatAtr,BWstat      ; Set B&W defaults for status
  284.             Mov     ScrnAtr,BWscrn      ; line and screen background
  285.             Cmp     DL,2                ; If mode 2
  286.             Je      VidExit             ; Then Done
  287.             Mov     DL,2                ; Else use B&W text mode
  288. chmode:     Mov     AL,DL               ; Set video mode
  289.             Xor     AH,AH
  290.             Int     10h
  291.             Mov     AX,0500h            ; Set video page 0
  292.             Int     10h
  293.             Mov     AX,24               ; Color or Mono Rows
  294.             Mov     rows,AX             ; Reset number of the
  295.             mov     lastrow,AX          ; last row and number of
  296.             Sub     AX,4                ; rows available for data
  297.             Mov     datrows,AX          ; from change before modechk
  298.             Mov     NewVid,1            ; Set flag
  299. VidExit:    Mov     DX,3200h            ; Hide cursor
  300.             Xor     BH,BH               ; off screen
  301.             Mov     AH,2
  302.             Int     10h                 ; Display 1st page
  303.             Jmp     AtStart
  304. extended:   Mov     AH,7                ; Obtain Code for
  305.             Int     21h                 ; extended Key
  306.             Mov     DI,OFFSET exKeys    ; Load address and
  307.             Mov     CX,LexKeys          ; length of key list
  308.             RepNE   ScaSB               ; If a key match
  309.             Je      GotoKey             ; Then go to work
  310.             Jmp     NextKey             ; Else ignore key
  311. GotoKey:    JcxZ    PgDnK               ; PgDnK is last
  312.             Dec     CX                  ; Backup through
  313.             JcxZ    DownK               ; table until
  314.             Dec     CX                  ; locate one of
  315.             JcxZ    EndK                ; seven keys and
  316.             Dec     CX                  ; do coresponding
  317.             JcxZ    PgUpK               ; scroll routine
  318.             Dec     CX
  319.             JcxZ    UpK
  320.             Dec     CX                  ; If Next to Last
  321.             JcxZ    AtStart             ; Then Is Home Key
  322.             Call    PrintMCBs           ; If PrintMCBs Then Exit
  323.             Jmp     Quit
  324. DownK:      Add     CX,1                ; DN - Forward 1 line
  325.             Jmp     SHORT GoPage
  326. PgDnK:      Add     CX,datrows          ; PGDN - Page forward
  327.             Jmp     SHORT GoPage
  328. UpK:        Sub     CX,1                ; UP - Go Back 1 line
  329.             Jmp     SHORT GoPage
  330. EndK:       Mov     DI,Ebuffer          ; END - End of Buffer
  331.             Mov     Pbuffer,DI
  332. PgUpK:      Sub     CX,datrows          ; PGUP - BackUp a Page
  333.  
  334. GoPage:     Mov     DI,Pbuffer
  335.             Mov     AL,10               ; If Going UP Lines
  336.             Jc      GoBack              ; Then Count Backwards
  337.             CLD                         ; Else Count Forward
  338. FindF:      Push    CX                  ; Preserve Row Count
  339.             Mov     CX,82               ; Set Maximum Row Bytes
  340.             RepNE   ScaSB
  341.             Pop     CX                  ; If NO Linefeeds Below
  342.             Jne     AtEnd               ; Then Must Be At End
  343.             Loop    FindF
  344.             Mov     Pbuffer,DI          ; Set Position
  345.             Call    Lines2Top           ; Get LineNumber
  346.             Mov     CX,LastNum          ; If Last Line
  347.             Sub     CX,datrows          ; Minus Display
  348.             Cmp     CX,LineNum          ; Is => LineNumber
  349.             Jnc     Show                ; Then Position Ok
  350.             Mov     AL,10
  351. AtEnd:      Mov     DI,Ebuffer          ; From End of Buffer
  352.             Mov     CX,datrows          ; Look Data Rows
  353.             Neg     CX                  ; Up or Backward
  354. GoBack:     STD
  355.             Sub     DI,2                ; Back Off Any Newline
  356.             Neg     CX                  ; Make Count Positive
  357. FindB:      Push    CX                  ; Preserve Row Count
  358.             Mov     CX,82               ; Set Maximum Row Bytes
  359.             RepNE   ScaSB
  360.             Pop     CX                  ; If NO Linefeeds Above
  361.             Jne     AtStart             ; Then Must Be At Start
  362.             Loop    FindB               ; Else Loop Until
  363.             CLD                         ; New Position
  364.             Add     DI,2                ; After Linefeed
  365.             Mov     Pbuffer,DI          ; Set New Position
  366.             Jmp     SHORT Show
  367. AtStart:    Mov     DI,Sbuffer          ; Reset Position to
  368.             Mov     Pbuffer,DI          ; Start of Buffer
  369. Show:       Call    Lines2Top           ; Count to Top Line
  370.             Add     AX,datrows          ; Adjust to Bottom Line
  371.             Cmp     AX,LastNum          ; If NOT past last
  372.             Jle     LineOk              ; Then line is Ok
  373.             Mov     AX,LastNum          ; Else make it Last
  374. LineOk:     Mov     DI,OFFSET statline[9]
  375.             Xor     DX,DX               ; Store Line
  376.             Call    StoreVal            ; Number and
  377.             Mov     AX,LastNum          ; Number of
  378.             Add     DI,6                ; Last Line
  379.             Call    StoreVal
  380.             Mov     BL,StatAtr          ; Set attribute for
  381.             Mov     attr,BL             ; status & headings
  382.             Xor     BP,BP               ; Initialize counter
  383.             Mov     SI,OFFSET headline  ; Store heading lines
  384. HDloop:     Mov     AX,BP               ; Set Video Line Number
  385.             Call    Line2Vid            ; Write one line
  386.             Inc     BP                  ; Count the heading line
  387.             Cmp     BP,4                ; If NOT yet 4 lines
  388.             Jc      HDloop              ; Then loop until 4
  389.             Mov     BL,ScrnAtr          ; Change attribute for
  390.             Mov     attr,BL             ; data buffer display
  391.             Mov     SI,Pbuffer          ; Index to Position
  392. DatLoop:    Mov     AX,BP               ; Set Video Line Number
  393.             Call    Line2Vid            ; Write line
  394.             Inc     BP                  ; Count row displayed
  395.             Cmp     SI,Ebuffer          ; If position => end
  396.             Jnc     PageDone            ; Then page is done
  397.             Cmp     BP,rows             ; Else If NOT Last Row
  398.             Jc      DatLoop             ; Then loop Until done
  399. PageDone:   Mov     BL,StatAtr
  400.             Mov     attr,BL             ; Load attribute for
  401.             Mov     SI,OFFSET statline  ; writing status line
  402.             Mov     AX,BP
  403.             Call    Line2Vid            ; Write status line
  404. NextKey:    Mov     AH,7
  405.             Int     21h                 ; Get key code
  406.             Cmp     AL,27               ; If ESCape key
  407.             Je      Quit                ; Then end ShowMCBs
  408.             Or      AL,AL               ; Else If NOT null
  409.             Jnz     NextKey             ; Then ignore key
  410.             Jmp     extended            ; Else get extended
  411.  
  412. Quit:       Cmp     NewVid,1            ; If video not changed
  413.             Jne     ThatsAll            ; Then That's All
  414.             Mov     AL,mode             ; Else Restore
  415.             Xor     AH,AH               ; video mode
  416.             Int     10h                 ; page and
  417.             Mov     AL,pag              ; cursor
  418.             Mov     AH,5
  419.             Int     10h
  420. ThatsAll:   Mov     CX,lastrow          ; Load last row and
  421.             Mov     AX,rows             ; Calculate rows to
  422.             Sub     AX,CX               ; be scrolled blank
  423.             Xchg    CL,CH               ; Set Upper Left and
  424.             Mov     DX,CX               ; copy in order to
  425.             Add     DH,AL               ; adjust Lower Right
  426.             Mov     DL,columns-1        ; corner of window
  427.             Mov     AH,6                ; Call ROM BIOS to
  428.             Mov     BH,7                ; clear the window
  429.             Int     10h
  430.             Mov     DX,CX               ; Set cursor above
  431.             Dec     DH                  ; window so prompt
  432.             Xor     BH,BH               ; is on last line
  433.             Mov     AH,2                ; when Exit to DOS
  434.             Int     10h
  435.             Mov     AX,4C00h            ; Zero Error Level
  436.             Int     21h                 ; Exit to MS-DOS
  437. Main        ENDP
  438.  
  439. Retrace     PROC    ; Writes during horizontal retrace (CGA)
  440.             Push    BX
  441.             Mov     BX,AX               ; Save char/attr
  442. lscan2:     In      AL,DX               ; Look in the port
  443.             Shr     AL,1                ; until it goes low
  444.             Jc      lscan2
  445.             CLI
  446. hscan2:     In      AL,DX               ; Look in the port
  447.             Shr     AL,1                ; until it goes high
  448.             Jnc     hscan2
  449.             Mov     AX,BX               ; Restore and write
  450.             StoSW                       ; Character/Attribute
  451.             STI
  452.             Pop     BX
  453.             Ret
  454. Retrace     ENDP
  455.  
  456. Line2Vid    PROC
  457.             Push    ES                  ; Preserve SegReg Used
  458.             Xor     DX,DX               ; Clear Flag for Scan
  459.             Cmp     cga,1               ; If NOT CGA
  460.             Jne     noscan              ; Then leave zero
  461.             Mov     DX,03DAh            ; Else load port #
  462. noscan:     Mov     ES,VidAdr           ; Load Video Segment in
  463.             Mov     CX,80               ; Which to Write a Line
  464.             Mov     BX,80*2             ; Bytes per row Times
  465.             Mul     BL                  ; Starting Row Equals
  466.             Mov     DI,AX               ; Starting Destination
  467.             Mov     AH,attr             ; Set Video Attribute
  468.  
  469. movechar:   LodSB                       ; Get character
  470.             Cmp     AL,13               ; If End of Data Line
  471.             Je      fillspc             ; Then end display line
  472.             Or      DX,DX               ; Else if NOT CGA
  473.             Je      notCGA              ; Then Write without delay
  474.             Call    Retrace             ; Else Write during retrace
  475.             Loop    movechar            ; Until End of Data Line
  476.             Jmp     SHORT chklf
  477. notCGA:     StoSW                       ; If end of display line
  478.             Loop    movechar            ; Then find End of Data Line
  479.             Jmp     SHORT chklf
  480. fillspc:    Mov     AL," "              ; Fill with space
  481.             Or      DX,DX               ; If NOT CGA Video
  482.             Je      space2              ; Then write direct
  483. space1:     Call    Retrace             ; Else write during retrace
  484.             Loop    space1              ; Until end of display line
  485.             Inc     SI                  ; Adjust for Data line LF
  486.             Jmp     SHORT L2Vexit       ; Return Position
  487. space2:     Rep     StoSW               ; Write
  488.             Inc     SI                  ; Adjust for LF
  489.             Jmp     SHORT L2Vexit       ; Return Position
  490. chklf:      Mov     AH,10
  491.             LodSB                       ; Load and compare
  492.             Cmp     AL,AH               ; If NOT Data Line LF
  493.             LoopNE  chklf               ; Then Loop Until Find
  494. L2Vexit:    Pop     ES                  ; Restore SegReg Used
  495.             Ret
  496. Line2Vid    ENDP
  497.  
  498. GetMCBs     PROC
  499.             Mov     CS:SavePtr,DI       ; Update MCBS Info Ptr
  500.             Mov     CS:SubF,0           ; Flag NOT in Sub-Blocks
  501.             Mov     BP,CS:Next          ; Re-Group at Next MCB
  502. NUPSEG:     Mov     DS,BP
  503.             Cmp     BYTE PTR DS:[0],'Z' ; If End Block
  504.             Je      CkBack              ; Then Real?
  505.             Cmp     BYTE PTR DS:[0],'M' ; Else If NOT 'M'
  506.             Jne     UpFast              ; Then Search
  507. CkBack:     Cmp     WORD PTR DS:[1],8   ; If DOS Owner
  508.             Jbe     CkSize              ; Or Owner Is
  509.             Cmp     WORD PTR DS:[1],BP  ; After MCB
  510.             Ja      CkSize              ; Then Real?
  511. UpFast:     Mov     CX,4
  512.             Shr     BP,CL               ; Shift Bits to Even
  513.             Shl     BP,CL               ; XXX0 Segment
  514.             Add     BP,10h              ; Add 1/4 k
  515.             Or      BP,BP               ; Search Until
  516.             Jnz     NUPSEG              ; MCBs End
  517.             Push    CS
  518.             Pop     DS                  ; Restore DS to Data
  519.             Jmp     PutMCBs             ; Store Information
  520.  
  521. CkSize:     Mov     AX,DS               ; If Size = MCB
  522.             Inc     AX                  ; Plus 1 Plus
  523.             Add     AX,DS:[3]           ; Length Carries
  524.             Jc      UpFast              ; Then NOT MCB
  525.             Mov     CS:Next,AX          ; Else Set Next
  526. SetSeg:     Mov     DS,BP
  527.             Xor     SI,SI               ; Point to MCB ID
  528.             Mov     AX,BP
  529.             StoSW                       ; Store MCB's Address
  530.             Inc     BP                  ; Advance a Paragraph
  531.             LodSB
  532.             Push    DI
  533.             Lea     DI,SubCBIs          ; Set for Scanning
  534.             Mov     CX,11               ; Eleven ID Bytes
  535.             RepNE   ScaSB
  536.             Pop     DI                  ; If Valid ID
  537.             Je      SaveID              ; Then Continue
  538.             Sub     DI,2                ; Else Re-Group
  539.             Mov     WORD PTR ES:[DI],0
  540.             Jmp     GetMCBs
  541. SaveID:     Mov     AH,CL               ; Store the
  542.             StoSW                       ; Letter/Code
  543.             LodSW
  544.             StoSW                       ; Store and Save
  545.             Mov     DX,AX               ; Block Owner/SEG
  546.             LodSW
  547.             StoSW                       ; Store and Save
  548.             Mov     BX,AX               ; Block Length
  549.             Mov     CX,8
  550.             Add     SI,3                ; Point to Name Area
  551.             Push    DS                  ; Preserve MCB Segment
  552.             Cmp     DX,0FFFAh           ; If NOT 386MAX Data
  553.             Jne     TestFE              ; Then Check Self-Load
  554.             Mov     DS,BP               ; Else Next Paragraph
  555.             Sub     SI,4                ;  has Name "UMB"
  556.             Jmp     Short LoadNB
  557. TestFE:     Cmp     DX,0FFFEh           ; If Is Self-Loaded
  558.             Je      LoadNB              ; Then Skip Other Tests
  559.             Cmp     DX,0FFFFh           ; Else If NOT Device/Resvd.
  560.             Jne     TestSF              ; Then Use MCB for Name
  561.             Mov     DS,BP               ; Else Try Device Name
  562.             Add     SI,2
  563.             Jmp     Short LoadNB
  564. TestSF:     Test    CS:SubF,1           ; If in Sub-Blocks
  565.             Jnz     LoadNB              ; Then Name Bytes
  566.             Push    SI                  ; Else Preserve
  567.             Push    DI                  ; Pointers and
  568.             Push    CX                  ; Counter for
  569.             Mov     CX,5                ; Check Whether
  570.             Mov     DI,OFFSET CS:Watch  ; Name Is "WATCH"
  571.             RepE    CmpSB
  572.             Jne     NoMatch             ; If Was "WATCH"
  573.             Mov     CS:WatchF,BP        ; Then Store Segment
  574. NoMatch:    Pop     CX                  ; Else Restore Name
  575.             Pop     DI                  ; Length and Positions
  576.             Pop     SI
  577. LoadNB:     LodSB
  578.             Cmp     AL,"!"              ; If Space or Less
  579.             Jb      ChkSeg              ; Or If Above Upper
  580.             Cmp     AL,"Z"              ; Case Alphabetic
  581.             Ja      ChkSeg              ; Then End Copying
  582.             StoSB                       ; Else Copy Bytes
  583.             Loop    LoadNB              ; Until 8 Or Invalid
  584. ChkSeg:     Pop     DS
  585.             Add     DI,CX               ; Adjust to Next Array
  586.  
  587.             Mov     AX,BP               ; If Next Block Ok
  588.             Add     AX,BX               ; Then Check If In
  589.             Jnc     CkSubs              ; Sub-Blocks Or Next
  590.             Mov     CX,16               ; Else Re-Set 16
  591.             Sub     DI,CX               ; Byte MCBs Array
  592.             Push    DI
  593.             Xor     AL,AL               ; Null the Bytes and
  594.             Rep     StoSB               ; Re-Group at Next MCB
  595.             Pop     DI
  596.             Jmp     GetMCBs
  597. CkSubs:     Cmp     AX,CS:Next          ; If In SubBlocks
  598.             Jc      AddLen              ; Then Continue
  599.             Mov     CS:SubF,0           ; Else End Subs
  600.             Mov     CS:Next,AX          ; Set New Next
  601.             Cmp     BP,CS:Menv
  602.             Je      AddLen              ; If Master Environment
  603.             Or      DX,DX               ; Or If Was "Free" Block
  604.             Jz      AddLen              ; Then Advance to Next MCB
  605.             Cmp     DX,8                ; Else If DOS is Owner
  606.             Je      LookNP              ; Then Look at Next Paragraph
  607.             Cmp     BP,CS:[2]           ; Else If In Conventional
  608.             Jc      AddLen              ; Then Can't Be Sub-Block
  609. LookNP:     Mov     DS,BP               ; Else Look at Next Paragraph
  610.             Mov     AL,DS:[0]           ; Load Byte for Block ID
  611.             Push    DI
  612.             Lea     DI,SubCBIs          ; Set for Scanning
  613.             Mov     CX,11               ; Eleven ID Bytes
  614.             RepNE   ScaSB
  615.             Pop     DI                  ; If NOT a Valid Sub-Block
  616.             Jne     AddLen              ; Then Advance to Next MCB
  617.             Mov     CS:SubF,1           ; Else Work on Sub-Blocks
  618.             Jmp     SetSeg
  619. AddLen:     Add     BP,BX               ; Work MCB at MCB+1 + Length
  620.             Jmp     SetSeg
  621. PutMCBs:    Mov     DI,OFFSET Buffer    ; Point to Buffer and
  622.             Mov     SI,OFFSET MCBS      ; Information for Display
  623. PMloop:     Mov     BX,SI               ; Save Basic Index
  624.             Cmp     SI,SavePtr          ; If Last MCB NOT Done
  625.             Jb      NextMCB             ; Then Work Next MCB
  626.             Jmp     PMexit              ; Else End Line and Exit
  627. NextMCB:    LodSW
  628.             Mov     BP,AX               ; Initialize as
  629.             Inc     BP                  ; Process Owner
  630.             Call    StoreHex            ; Store MCB Address
  631.             LodSB
  632.             LodSB                       ; Convert MCB Type
  633.             CBW                         ; Code to Word
  634.             Mov     CL,3                ; Offset to 8
  635.             Shl     AX,CL               ; Byte Types
  636.             Push    SI
  637.             Mov     SI,OFFSET TypeMCB   ; Point to Appropriate
  638.             Add     SI,AX               ; MCB Type String
  639.             Mov     CX,8                ; Store 8 Byte
  640.             Rep     MovSB               ; Type String
  641.             Pop     SI
  642.             LodSW                       ; Load and Store
  643.             Call    StoreHex            ; Hex Owner/SEG
  644.             LodSW                       ; Load Length Word
  645.             Add     DI,6                ; Allow 6 Digits and
  646.             Call    StorePara           ; Store Decimal Length
  647.             Inc     DI                  ; Advance to Identity
  648.             Mov     CX,8                ; Set Max Name Length
  649.             Mov     AX,[BX+4]           ; Recover Owner Word
  650.             Cmp     AX,BP               ; If Owner=MCB+1
  651.             Je      PNloop              ; Then Name Stored
  652.             Cmp     AX,0FFFAh           ; Else Other 386MAX
  653.             Jae     PNloop              ; Load Name May Be Bad
  654.             Cmp     AX,CX               ; Else If Above DOS Owner
  655.             Ja      PreNam              ; Then May Have a Name
  656.             Cmp     AX,CX               ; If DR-DOS Self-Load
  657.             Je      PNloop              ; Then Name was Stored
  658.             Mov     CX,6                ; Else Store Six Bytes
  659.             Push    SI
  660.             Lea     SI,FreeM            ; From " Free   DOS "
  661.             Dec     DI                  ; Back-Up to Space
  662.             Or      AX,AX               ; If Block Available
  663.             Jz      PutMsg              ; Then Put "Free " in Name
  664.             Add     SI,CX               ; Else Put " DOS " in Name
  665. PutMsg:     Rep     MovSB
  666.             Pop     SI                  ; Recover MCBS Pointer
  667.             Mov     CX,8                ; Set Max Name Length
  668. PreNam:     Mov     DX,OFFSET MCBS      ; Point to First MCBS
  669.             Cmp     AX,CX               ; If System 8
  670.             Je      PNloop              ; Then SCorSD
  671.             Ja      PNfind              ; Else Above Find
  672.             Jmp     PLdone              ; Else 0-7 is Done
  673. PNfind:     Mov     SI,DX               ; Set for
  674.             Add     DX,16               ; Next MCB Struc
  675.             LodSW                       ; Get MCB Address
  676.             Add     SI,6                ; Point to Filename
  677.             Inc     AX                  ; If Para After MCB
  678.             Cmp     AX,[BX+4]           ; Is the Process SEG
  679.             Je      PNloop              ; Then Use its Name
  680.             Cmp     SI,SavePtr          ; If Any More Used MCBS's
  681.             Jb      PNfind              ; Then Continue Looking
  682.             Jmp     PLdone              ; Else NOT Part of Process
  683. PNloop:     LodSB
  684.             Or      AL,AL               ; If NULL Byte
  685.             Jz      PNdone              ; Then Done
  686.             StoSB                       ; Else Store
  687.             Loop    PNloop
  688. PNdone:     Mov     AX,[BX+4]           ; Load Owner Word
  689.             Mov     CX,13               ; Set Length for
  690.             Mov     SI,OFFSET IsFar+39  ; <Master Env.>, etc
  691.             Cmp     AX,-1               ; If Device/Reserved
  692.             Je      GoVecs              ; Then No Command Line
  693.             Mov     DI,Pbuffer          ; Else Point to
  694.             Add     DI,36               ; Command Line
  695.             Cmp     BP,Menv             ; If Is <Master Env>
  696.             Je      MoveRem             ; Then Write and Done
  697.             Cmp     BP,AX               ; Else If MCB+1=Owner
  698.             Je      CmdLine             ; Then Copy Command Line
  699.             Sub     SI,CX               ; Else <386MAX Data> ?
  700.             Cmp     BP,CS:[2]           ; If Conventional Block
  701.             Jb      NOT386              ; Then No 386MAX Data
  702.             Cmp     XMSmgr,3            ; Else If XMSmgr is 386 MAX
  703.             Je      MAX386              ; Then May Be <386MAX Data>
  704. NOT386:     Sub     SI,CX               ; Else May Be <Environment>
  705.             Cmp     BP,AX               ; If Below the Process
  706.             Jb      MoveRem             ; Then <Environment>
  707.             Sub     SI,CX               ; Else <FarDataArea>
  708.             Jmp     Short MoveRem
  709. MAX386:     Cmp     AX,0FFFEh           ; If 386MAX Self-Loaded
  710.             Je      CmdLine             ; Then Copy Command Line
  711.             Cmp     AX,0FFFAh           ; Else If Self Load Data
  712.             Je      MoveRem             ; Then Is <386MAX Data>
  713.             Cmp     BP,AX               ; Or If Below Owner
  714.             Jb      MoveRem             ; Then Is <386MAX Data>
  715.             Sub     SI,CX               ; Else <Environment>
  716. MoveRem:    Rep     MovSB
  717.             Cmp     AX,8                ; If DOS Block
  718.             Je      PLdone              ; Or If NOT
  719.             Cmp     SI,OFFSET IsFar+13  ; <FarDataArea>
  720.             Ja      PLdone              ; Then NO Vectors
  721.             Jmp     Short GoVecs        ; Else Check Vectors
  722. CmdLine:    Push    BX                  ; Preserve Index and
  723.             Push    DS                  ; Data Segment Register
  724.             Mov     DS,BP               ; Point to Owner's
  725.             Mov     SI,80h              ; Command Tail
  726.             LodSB                       ; If Length of
  727.             CBW                         ; Command Line
  728.             Or      AX,AX               ; Word is Zero
  729.             Jz      CLexit              ; Then No Parms
  730.             Mov     BX,AX               ; Else If NO
  731.             Cmp     Byte Ptr [SI+BX],13 ; Ending CR
  732.             Jne     CLexit              ; Then NO Parms
  733.             Mov     CX,16               ; Else If NOT
  734.             Cmp     AX,CX               ; Over 16 Bytes
  735.             Jbe     ClenOk              ; Then AX Bytes
  736.             Mov     AX,13               ; Else 13 Bytes
  737.             Mov     CX,".."             ; Plus Elipsis
  738. ClenOk:     Xchg    AX,CX               ; Copy AX Bytes of
  739.             Rep     MovSB               ; Command Parameters
  740.             Cmp     AX,".."             ; If NOT Elipsis(ed)
  741.             Jne     CLexit              ; Then Line Finished
  742.             StoSW                       ; Else Store
  743.             StoSB                       ; Elipsis...
  744. CLexit:     Pop     DS                  ; Restore Data SEGment and
  745.             Pop     BX                  ; Restore Index
  746. GoVecs:     Mov     AX,CS
  747.             Cmp     AX,BP               ; If PSP of ShowMCBs
  748.             Je      PLdone              ; Then Avoid "Spurious"
  749.             Call    Vectors             ; Chained/Hooked Vectors
  750. PLdone:     Mov     AX,0A0Dh            ; Carriage Return and
  751.             StoSW                       ; Line Feed Ends Line
  752.             Mov     Pbuffer,DI          ; Keep Pbuffer Current
  753.             Mov     SI,BX               ; Back-Up to Start at
  754.             Add     SI,16               ; Next MCBS' Member
  755.             Jmp     PMloop              ; Loop Until MCBs Done
  756. PMexit:     Mov     AX,0A0Dh
  757.             StoSW                       ; End Last Line
  758.             Call    PutEMMS             ; Check EMMS Information
  759.             Mov     AX,Word Ptr XMS     ; Load Total Free eXtended
  760.             Or      AX,Word Ptr XMS[2]  ; If NO eXtended
  761.             Jz      PMecnv              ; Then Skip Line
  762.             Mov     AX,Word Ptr XMS     ; Else Load Total
  763.             Xor     DX,DX               ; Prepare and
  764.             Add     DI,7                ; Position to
  765.             Call    StoreVal            ; Store Kilo
  766.             Lea     SI,BytesE           ; Bytes and
  767.             Mov     CX,MsgLen           ; Trailing
  768.             Rep     MovSB               ; Message
  769.             Mov     AX,Word Ptr XMS[2]  ; Prepare and
  770.             Add     DI,7                ; Position to
  771.             Call    StoreVal            ; Store Kilo
  772.             Mov     CX,MsgLen           ; Bytes and
  773.             Rep     MovSB               ; Message
  774. PMecnv:     Mov     AX,CS:[2]           ; End of Conventional
  775.             Mov     CX,CS               ; Memory Minus
  776.             Sub     AX,CX               ; ShowMCBs PSP =
  777.             Add     DI,7                ; Paragraphs
  778.             CAll    StorePara           ; as bytes of
  779.             Lea     SI,BytesM           ; conventional
  780.             Mov     CX,MsgLen           ; memory available
  781.             Rep     MovSB               ; at ShowMCBs'
  782.             Mov     AX,CS               ; ProgramSegmentPrefix
  783.             Call    StoreHex
  784.             Mov     Pbuffer,DI          ; Update Pointer to Buffer
  785.             Ret
  786. GetMCBs     ENDP
  787.  
  788. Vectors     PROC
  789.             Push    BX                  ; Preserve MCB Index
  790.             Mov     DI,Pbuffer          ; Position Show Index to
  791.             Add     DI,53               ; Start of Vector Area
  792.             Cmp     WatchF,0            ; If WATCH NOT Installed
  793.             Jz      UseHook             ; Then Use Hooked Vectors
  794.             Mov     DS,WatchF           ; Else Use Chained
  795.             Mov     SI,104h             ; Get Next Vector
  796.             LodSW                       ; Position in
  797.             Mov     SI,320h             ; Vector Change
  798.             Add     AX,SI               ; Storage Area
  799.             Mov     CS:Vpos,AX          ; Store for Comparison
  800.             Sub     SI,8                ; Get a Running Start
  801.             Xor     BX,BX               ; Zero Vector Counter
  802. FFLoop:     Add     SI,8                ; If Next Record
  803.             Cmp     SI,CS:Vpos          ; Is Table End
  804.             Jnc     UseHook             ; Then Check Hooked
  805. CkPSPID:    Cmp     Word Ptr [SI],-1    ; If NOT pspid
  806.             Jne     FFLoop              ; Or If NOT the
  807.             Cmp     [SI+2],BP           ; Desired SEGment
  808.             Jne     FFLoop              ; Then Keep Looking
  809. WatchL:     Add     SI,8                ; Else If Next Record
  810.             Cmp     SI,CS:Vpos          ; Is Past Table End
  811.             Jnc     LillyPad            ; Or If Next PSPID
  812.             Cmp     WORD PTR [SI],-1    ; Then Exit Done
  813.             Je      INTExit
  814.             Cmp     BYTE PTR [SI+1],1   ; If Disabled Vector
  815.             Je      WatchX              ; Then "DISABLED" Exit
  816.             Cmp     BX,9                ; Else If More Columns
  817.             Jc      WatchW              ; Then Store Vector
  818.             Mov     WORD PTR ES:[DI],0A0Dh ; Else End Line
  819.             Mov     CS:Pbuffer,DI       ; UpDate to NewLine
  820.             Add     DI,55               ; Start new line
  821.             Xor     BX,BX               ; Update counter
  822. WatchW:     Mov     AX,[SI]             ; Get Vector Number
  823.             Call    Val2ASCh            ; Store 2 HEX Digits + Space
  824.             Inc     BX                  ; Count Vector
  825.             Jmp     WatchL              ; Loop until exit
  826. WatchX:     Push    CS
  827.             Pop     DS                  ; Restore Data Segment
  828.             Mov     SI,OFFSET DisaM     ; Copy the Message
  829.             Mov     CX,DisaLen          ; " D I S A B L E D "
  830.             Rep     MovSB               ; and Exit Vectors
  831. LillyPad:   Jmp     Short INTExit
  832.  
  833. UseHook:    Pop     BX                  ; Restore Index to
  834.             Push    BX                  ; Use for to get
  835.             Mov     DX,ES:[BX+6]        ; Program Length
  836.             Cmp     DX,800h             ; If .COM Size
  837.             Jc      UHlimit             ; Then in Limits
  838.             Mov     DX,800h             ; Else Shorten
  839. UHlimit:    Add     DX,BP               ; Start+Len = Limit
  840.             Cmp     BP,0B800h           ; If Below CGA/VGA
  841.             Jb      UHnoVid             ; Then Probably Ok
  842.             Cmp     DX,0C000h           ; Else If In Video
  843.             Jbe     INTExit             ; Then No Vectors
  844. UHnoVid:    Xor     BX,BX               ; Initialize INT at
  845.             Mov     DS,BX               ; Beginning of DOS
  846.             Mov     SI,BX               ; Interrupt Table &
  847.             Mov     CX,256              ; Double Word Count
  848. UH_Loop:    LodSW
  849.             LodSW                       ; If SEG of INT
  850.             Cmp     AX,BP               ; Is Below Program
  851.             Jb      Loop2UH             ; Or If Above Limit
  852.             Cmp     AX,DX               ; Then Loop for Next
  853.             Ja      Loop2UH             ; Until End of INTs
  854.             Mov     AX,BX               ; Else Store 2 HEX
  855.             Call    Val2ASCh            ; Digits + Space
  856.             Mov     AX,CS:Pbuffer       ; If start of current row
  857.             Add     AX,columns-2        ; Up to position after end
  858.             Cmp     DI,AX               ; Is greater than pointer
  859.             Jc      Loop2UH             ; Then Loop Until EOL/Done
  860.             Mov     AX,0A0Dh            ; Else Start a New Line
  861.             StoSW
  862.             Mov     CS:Pbuffer,DI       ; UpDate to NewLine
  863.             Add     DI,53               ; Position to INT Nos.
  864. Loop2UH:    Inc     BX                  ; Increment INT Number
  865.             Loop    UH_Loop             ; Loop to End of Table
  866. INTExit:    Push    CS
  867.             Pop     DS                  ; Restore
  868.             Push    CS                  ; Segments to
  869.             Pop     ES                  ; ShowMCBs PSP
  870.             Pop     BX                  ; Restore Index
  871.             Ret
  872. Vectors     ENDP
  873.  
  874. Val2ASCh    PROC                        ; Machine Code to Divide
  875.             DB      0D4h,10h            ; AL/16 AL=MS and AH=LS
  876.             Or      AX,3030H            ; Convert to ASCII
  877.  
  878.             Cmp     AL,"9"              ; If Decimal ASCII
  879.             Jbe     ALexit              ; Then Digit is Ok
  880.             Add     AL,7                ; Else Make "A" - "F"
  881. ALexit:     Cmp     AH,"9"
  882.             Jbe     AHexit              ; Do Same With MS Digit
  883.             Add     AH,7
  884. AHexit:     Xchg    AL,AH               ; Reverse MS and LS Digits
  885.             StoSW                       ; Store 2 HEX ASCII Digits
  886.             Inc     DI                  ; Terminate With a Space
  887.             Ret
  888. Val2ASCh    ENDP
  889.  
  890. PutEMMS     PROC
  891.             Push    DI                  ; Preserve Storage
  892.             Push    ES                  ; Segment:Pointer
  893.             Mov     AX,3567h            ; Get Vector for
  894.             Int     21h                 ; Function 67hex
  895.             Mov     DI,000Ah            ; Scan Device
  896.             Mov     CX,8                ; Name for:
  897.             Lea     SI,EmsName          ; "EMMXXXX0"
  898.             Rep     CmpSB
  899.             Pop     ES                  ; Restore ES:DI
  900.             Pop     DI                  ; If NOT "EMMXXXX0"
  901.             Jne     EmsErrX             ; Then Error Exit
  902.             Mov     AH,46h              ; Or If version
  903.             Int     67h                 ; number request
  904.             Or      AH,AH               ; returns error
  905.             Jnz     EmsErrX             ; Then Error Exit
  906.             Mov     SI,OFFSET emmshdg   ; Else store 1st
  907.             Mov     CX,emmlen1          ; Heading Line
  908.             Rep     MovSB
  909.             Call    SHex_1              ; Store Major/Minor
  910.             Dec     DI                  ; EMMS Version and
  911.             Mov     AH,ES:[DI]          ; Insert Dot
  912.             Mov     AL,"."              ; Move Minor
  913.             StoSW                       ; Number
  914.             Mov     AL,')'              ; Close Parens.
  915.             StoSB
  916.             Mov     CX,emmlen2          ; Add 2nd heading
  917.             Rep     MovSB               ; line lead-in to
  918.             Mov     AH,41h              ; EMS Page Frame
  919.             Int     67h
  920.             Or      AH,AH               ; If Request Fails
  921.             Jnz     EmsErrX             ; Then Error Exit
  922.             Mov     AX,BX               ; Else store HEX
  923.             Call    StoreHex            ; page frame plus
  924.             Mov     AL,")"              ; close parenthesis
  925.             Mov     ES:[DI-1],AL
  926.             Mov     AX,0A0Dh            ; End the line
  927.             StoSW
  928.             Mov     AH,4Bh              ; Get Handle
  929.             Int     67h                 ; Count in BX
  930.             Or      AH,AH               ; If Response
  931.             Jz      EmPages             ; Then Map Pages
  932. EmsErrX:    Mov     SI,OFFSET EMSerm    ; Else store EMS
  933.             Mov     CX,emerml           ; Error Message
  934.             Rep     MovSB
  935.             Jmp     EmmExit
  936. EmPages:    Mov     CX,BX               ; Set Handle Counter
  937.             Inc     CX                  ; for zero thru [bx]
  938.             Mov     handles,CX
  939. HndLoop:    Mov     AH,4Ch              ; Get
  940.             Mov     DX,handles          ; Assigned
  941.             Sub     DX,CX               ; Handle
  942.             Int     67h                 ; Pages
  943.             Or      AH,AH               ; If Error
  944.             Jnz     NoPages             ; Then skip
  945.             Or      BX,BX               ; Else if > 0
  946.             Jnz     PagesOk             ; Then store
  947. NoPages:    Loop    HndLoop             ; Else loop until
  948.             Jmp     SHORT HndExit       ; CX handles done
  949. PagesOk:    Xor     AX,AX
  950.             Push    DX                  ; Preserve and
  951.             Add     DI,6                ; Position for
  952.             Xchg    AX,DX               ; Handle Number
  953.             Call    StoreVal
  954.             Add     DI,9                ; Position
  955.             Mov     AX,BX               ; for pages
  956.             Call    StoreVal
  957.             Add     Tpages,BX           ; Accumulate Total
  958.             Add     DI,9                ; Position for
  959.             Mov     AX,BX               ; Handle KBytes
  960.             Call    StorePara
  961.             Add     DI,3                ; Position for
  962.             Mov     AX,5300h            ; User Name
  963.             Pop     DX
  964.             Int     67h                 ; Advance Past
  965.             Add     DI,8                ; Name Area
  966.             Mov     AX,0A0Dh            ; End the line
  967.             StoSW                       ; Loop until
  968.             Loop    HndLoop             ; CX'em done
  969.  
  970. HndExit:    Mov     AH,42h              ; Get Free
  971.             Int     67h                 ; Pages and
  972.             Add     Tpages,BX           ; Adjust Total
  973.             Mov     SI,OFFSET FreeM
  974.             Mov     CX,6                ; Store "  free"
  975.             Rep     MovSB               ; lead-in and
  976.             Add     DI,9                ; Position for
  977.             Mov     AX,BX               ; Free Pages
  978.             Xor     DX,DX
  979.             Call    StoreVal
  980.             Add     DI,9                ; Position for
  981.             Mov     AX,BX               ; Free KBytes
  982.             Call    StorePara
  983.             Mov     SI,OFFSET dashes+26 ; Space Over
  984.             Mov     CX,11               ; and dash-out
  985.             Rep     MovSB               ; UserName
  986.             Mov     AX,0A0Dh            ; End the line
  987.             StoSW
  988.             Mov     SI,OFFSET TotlM     ; Store
  989.             Mov     CX,6                ; " total"
  990.             Rep     MovSB               ; lead-in
  991.             Add     DI,9                ; Position for
  992.             Mov     AX,Tpages           ; Total Pages
  993.             Call    StoreVal
  994.             Add     DI,9                ; Position for
  995.             Mov     AX,Tpages           ; Total KBytes
  996.             Call    StorePara
  997.             Mov     SI,OFFSET dashes+26 ; Space Over
  998.             Mov     CX,11               ; and dash-out
  999.             Rep     MovSB               ; UserName
  1000. EmmExit:    Mov     AX,0A0Dh            ; End the line
  1001.             StoSW                       ; and Add a
  1002.             StoSW                       ; New Line
  1003.             Ret
  1004. PutEMMS     ENDP
  1005.  
  1006. Lines2Top   PROC
  1007.             Mov     AX,10               ; Count Line Feeds
  1008.             Push    CX                  ; Preserve Counter and
  1009.             Push    DI                  ; If Buffer Pointer
  1010.             Mov     CX,DI               ; Is at Buffer Start
  1011.             Sub     CX,Sbuffer          ; Then NO Lines Above
  1012.             JcxZ    L2Tdone             ; Else Use Counter to
  1013.             Std                         ; Scan Back for Line Feeds
  1014.  
  1015. L2Tloop:    RepNE   ScaSB               ; If NO MORE Line Feeds
  1016.             Jne     L2Tdone             ; Then All Were Counted
  1017.             Inc     AH                  ; Else Accumulate Number
  1018.             JcxZ    L2Tdone             ; Until Reach the Top
  1019.             Jmp     L2Tloop
  1020. L2Tdone:    Mov     AL,AH               ; Make Line Count
  1021.             Xor     AH,AH               ; Into a Word Value
  1022.             Mov     LineNum,AX          ; Store Line Number
  1023.             Cld                         ; Restore Direction
  1024.             Pop     DI                  ; Buffer Pointer
  1025.             Pop     CX                  ; and Counter
  1026.             Ret                         ; AX = 0 to 255 Lines
  1027. Lines2Top   ENDP
  1028.  
  1029. StorePara   PROC
  1030.             Push    DX                  ; Preserve
  1031.             Push    AX                  ; Registers
  1032.             Push    CX                  ; Used
  1033.             Mov     CX,16               ; Convert to Bytes as
  1034.             Mul     CX                  ; DoubleWord in DX:AX
  1035.             Pop     CX
  1036.             Call    StoreVal            ; Store DWord Value
  1037.             Pop     AX                  ; Restore
  1038.             Pop     DX                  ; Registers
  1039.             Ret                         ; Used
  1040. StorePara   ENDP
  1041.  
  1042. StoreVal    PROC                        ; Preserve
  1043.             Push    DI                  ; Registers
  1044.             Push    CX                  ; Used
  1045.             Mov     CX,10               ; Decimal Base 10
  1046.             Cmp     CX,DX               ; If DX:AX is Too Big
  1047.             Jb      SVabort             ; Then Abort Routine
  1048. SVloop:     Dec     DI                  ; Else Back-Up Pointer
  1049.             Div     CX                  ; Make Remainder
  1050.             Or      DL,'0'              ; ASCII Digit
  1051.             Mov     ES:[DI],DL          ; Store in Buffer
  1052.             Xor     DX,DX               ; Zero Remainder
  1053.             Or      AX,AX               ; Loop Until Zero
  1054.             Jnz     SVloop
  1055. SVabort:    Pop     CX                  ; Restore
  1056.             Pop     DI                  ; Registers
  1057.             Ret                         ; Used
  1058. StoreVal    ENDP
  1059.  
  1060. StoreHex    PROC                        ; AX Will Be Changed
  1061.             Push    AX                  ; Preserve the Word
  1062.             Inc     DI                  ; Add Leading Space
  1063.             Mov     AL,AH               ; Work on MSByte
  1064.             Call    SHex_1              ; Store 2 Digits
  1065.             Pop     AX                  ; Restore Value
  1066.             Call    SHex_1              ; Store LSByte Digits
  1067.             Mov     AL,' '              ; Add Trailing Space
  1068.             Jmp     SHORT SHexit
  1069. SHex_1:     Mov     AH,AL               ; Save Working Byte
  1070.             And     AL,0F0h             ; Isolate
  1071.             Shr     AL,1                ; Upper
  1072.             Shr     AL,1                ; Nibble
  1073.             Shr     AL,1                ; In the
  1074.             Shr     AL,1                ; AL Reg
  1075.             Call    SHex_2              ; Store as ASCII Digit
  1076.             Mov     AL,AH               ; Restore Byte and
  1077.             And     AL,0Fh              ; Isolate Lower Nibble
  1078. SHex_2:     Add     AL,'0'              ; Make ASCII Digit
  1079.             Cmp     AL,'9'+1            ; Check If Decimal
  1080.             Jb      SHexit              ; Decimal Ok to Store
  1081.             Add     AL,'A'-'9'-1        ; Else Make Hex 'A-F'
  1082. SHexit:     StoSB                       ; Store AL Character
  1083.             Ret                         ; Recurse or Return
  1084. StoreHex    ENDP                        ; Value is Destroyed
  1085.  
  1086. PrintMCBs   PROC
  1087.             Mov     AX,1300h            ; Write Message
  1088.             Mov     BH,pag              ; Video Page and
  1089.             Mov     BL,StatAtr          ; Attribute that
  1090.             Mov     BP,OFFSET FkeyMsg   ; Requests Choice
  1091.             Mov     CX,MsgLen+2         ; F7=PRN or F8=file
  1092.             Mov     DX,lastrow          ; Bottom Row in
  1093.             Xchg    DH,DL               ; DH and Column
  1094.             Mov     DL,16               ; 16 in DL with
  1095.             Int     10h                 ; ES:BP as Pointer
  1096.             Mov     BX,4                ; PRN Device Default
  1097. PrintKey:   Mov     AH,7
  1098.             Int     21h
  1099.             Or      AL,AL               ; Wait for Function Key
  1100.             Jnz     PrintKey
  1101.             Mov     AH,7
  1102.             Int     21h
  1103.             Cmp     AL,65               ; If F7
  1104.             Je      PrintBeg            ; Then PRN
  1105.             Cmp     AL,66               ; Else If NOT F8
  1106.             Jne     PrintKey            ; Then Wait for Choice
  1107.             Mov     DX,OFFSET helpdat-13
  1108.             Mov     AH,3Ch              ; Create ShowMCBs.PRN
  1109.             Xor     CX,CX               ; Normal Attributes
  1110.             Int     21h                 ; If Create Fails
  1111.             Jc      PrintBeg            ; Then Use PRN
  1112.             Mov     BX,AX               ; Else Use file
  1113. PrintBeg:   Mov     DI,Sbuffer          ; Scan from Start
  1114.             Call    PrintChk            ; SetUp for Scans
  1115. Scan4CR:    RepNE   ScaSB
  1116.             Inc     DX                  ; Count New Lines
  1117.             Cmp     ES:[DI+1],AH        ; If Reach helpdat
  1118.             Je      PrintOut            ; Then End Printing
  1119.             Cmp     DX,50               ; Else If < 50 Lines
  1120.             Jb      Scan4CR             ; Then Continue Scan
  1121.             ScaSB                       ; Else Look for a
  1122.             Sub     CX,2                ; Double CR,LF
  1123.             ScaSB                       ; If Double CR,LF
  1124.             Je      DoPrint             ; Then Print a Page
  1125.             Add     CX,2                ; Else Put Back
  1126.             Sub     DI,2                ; Count and Ptr
  1127.             Cmp     DX,58               ; Until 58 Lines
  1128.             Jb      Scan4CR             ; Continue Scan
  1129. DoPrint:    Call    PrintOut            ; Print to Here
  1130.             Jmp     Scan4CR
  1131. PrintOut:   Mov     AL,12               ; Change LF to FF
  1132.             StoSB                       ; Count the
  1133.             Dec     CX                  ; FormFeed
  1134.             Push    CX                  ; Save Count
  1135.             Mov     AH,40h              ; Write to BX
  1136.             Mov     CX,OFFSET statline  ; Contents of
  1137.             Mov     DX,OFFSET headline  ; Heading
  1138.             Sub     CX,DX               ; 4 Lines
  1139.             Int     21h
  1140.             Pop     CX                  ; Restore Byte Count
  1141.             Not     CX                  ; Set Length to Print
  1142.             Mov     DX,DI               ; Set DX to
  1143.             Sub     DX,CX               ; Start Place
  1144.             Mov     AH,40h              ; Write CX
  1145.             Int     21h                 ; Buffer Bytes
  1146. PrintChk:   Cmp Byte Ptr ES:[DI],255    ; If NOT at End of Data
  1147.             Jne     PrintSet            ; Then Set to Scan More
  1148.             Cmp     BX,4                ; Else If PRN Device
  1149.             Je      PrintSet            ; Then Go to Exit
  1150.             Mov     AH,3Eh              ; Else Close File
  1151.             Int     21h
  1152. PrintSet:   Mov     CX,-1               ; Counting from
  1153.             Mov     DX,4                ; After Heading for
  1154.             Mov     AX,0FF0Dh           ; Carriage Returns
  1155.             Ret
  1156. PrintMCBs   ENDP
  1157.             DB      25,'Start V Buffer',25
  1158. Buffer:
  1159. Cseg        ENDS
  1160.             END     Begin
  1161.